home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / AMISL083.ARJ / AMIS.MAC < prev    next >
Text File  |  1992-05-02  |  19KB  |  688 lines

  1. .XLIST
  2. ;-----------------------------------------------------------------------
  3. ; Alternate Multiplex Interrupt Specification Library
  4. ; AMIS.MAC    Public Domain 1992 Ralf Brown
  5. ;        You may do with this software whatever you want, but
  6. ;        common courtesy dictates that you not remove my name
  7. ;        from it.
  8. ;
  9. ; Version 0.83
  10. ; LastEdit: 5/2/92
  11. ;-----------------------------------------------------------------------
  12.  
  13. AMIS_VERSION equ 340    ;(version 3.4 of the Alternate Multiplex Interrupt Spec)
  14. AMISLIB_VERSION equ 083 ;(version 0.83 of this library)
  15.  
  16. ;-----------------------------------------------------------------------
  17. ; Return codes for various API calls
  18. ;
  19.  
  20. ; general, applies to all standard calls
  21. AMIS_NOTIMPLEMENTED      equ 0
  22. AMIS_SUCCESSFUL        equ 0FFh
  23.  
  24. ; additional return codes for Uninstall (function 02h)
  25. AMIS_UNINST_FAILED    equ 1
  26. AMIS_UNINST_WILL_DO    equ 2
  27. AMIS_UNINST_SAFE_ON    equ 3
  28. AMIS_UNINST_SAFE_OFF    equ 4
  29. AMIS_UNINST_TRYLATER     equ 5
  30.  
  31. ; additional return codes for Popup (function 03h)
  32. AMIS_POPUP_TRYLATER    equ 1
  33. AMIS_POPUP_WILLDO    equ 2
  34. AMIS_POPUP_BUSY        equ 3
  35. AMIS_POPUP_NEEDHELP    equ 4
  36.  
  37. ; additional return codes for Check Interrupt Chained (function 04h)
  38. AMIS_CHAIN_DONTKNOW    equ 1
  39. AMIS_CHAIN_HOOKED    equ 2
  40. AMIS_CHAIN_HOOKED_ADDR    equ 3
  41. AMIS_CHAIN_HOOKLIST    equ 4
  42. AMIS_CHAIN_NOTUSED    equ 0FFh
  43.  
  44. ;-----------------------------------------------------------------------
  45. ;
  46. ; Set up a shorthand for the segment containing all the resident code and
  47. ; data.
  48. ; Note: the alignment must be PARA for the code to be properly relocatable
  49. ; in small-code memory models.
  50. ;
  51. TSRcode@ MACRO
  52. TGROUP GROUP RESIDENT_CODE
  53. RESIDENT_CODE SEGMENT PUBLIC PARA 'TSRCODE'
  54.     ASSUME    DS:NOTHING,ES:NOTHING,SS:NOTHING
  55.     ASSUME    CS:TGROUP
  56.     ENDM
  57. TSRcodeEnd@ MACRO
  58. RESIDENT_CODE ENDS
  59.     ENDM
  60.  
  61. ;-----------------------------------------------------------------------
  62. ;
  63. ; Set up shorthands for the segments containing all the resident data,
  64. ; initialized and uninitialized.
  65. ;
  66. TSRdata@ MACRO
  67. RESIDENT_DATA SEGMENT PUBLIC BYTE 'TSRCODE'
  68.     ENDM
  69. TSRdataEnd@ MACRO
  70. RESIDENT_DATA ENDS
  71.     ENDM
  72.  
  73. TSRbss@ MACRO
  74. RESIDENT_BSS SEGMENT PUBLIC BYTE 'TSRCODE'
  75.     ENDM
  76. TSRbssEnd@ MACRO
  77. RESIDENT_BSS ENDS
  78.     ENDM
  79.  
  80. ;-----------------------------------------------------------------------
  81. ;
  82. ; Set up a shorthand for declaring all three resident segments and a group
  83. ; TGROUP for those segments.
  84. ;
  85. TSRgroup@ MACRO
  86. TSRcode@
  87. TSRcodeEnd@
  88. TSRdata@
  89. TSRdataEnd@
  90. TSRbss@
  91. TSRbssEnd@
  92. TGROUP GROUP RESIDENT_CODE,RESIDENT_DATA,RESIDENT_BSS
  93.     ENDM
  94.  
  95. ;-----------------------------------------------------------------------
  96. ;
  97. ; Some of the code in ALTMPX.ASM uses conditional assembly to handle
  98. ; segment registers differently in Tiny model than in other models, so
  99. ; we need to ensure that __TINY__ is defined in tiny model.
  100. ;
  101. IFDEF @Model        ; simplified memory models being used?
  102.   IF @Model eq 1    ; tiny model
  103.      IFNDEF __TINY__
  104.        __TINY__ equ 1
  105.      ENDIF ;NDEF
  106.   ENDIF
  107.   IF (@Model eq 1) or (@Model eq 2) or (@Model eq 3) ; Tiny, Small, or Compact?
  108.      DIST equ NEAR
  109.   ELSE
  110.      DIST equ FAR
  111.   ENDIF
  112. ELSE ;DEF @Model    ; else assume TCC/BCC memory-model #defines
  113.    IFDEF __TINY__
  114.       DIST equ NEAR
  115.    ELSEIFDEF __SMALL__
  116.       DIST equ NEAR
  117.    ELSEIFDEF __COMPACT__
  118.       DIST equ NEAR
  119.    ELSE
  120.       DIST equ FAR
  121.    ENDIF
  122. ENDIF
  123.  
  124. ;-----------------------------------------------------------------------
  125. ;
  126. ; installation flags (mainly internal use--see INSTALL_TSR below)
  127. ;
  128. BEST_FIT   equ 1    ; use best-fit rather than first-fit
  129. UMB_ONLY   equ 2    ; don't load into low memory, only into a UMB
  130. LOW_ONLY   equ 4    ; don't use UMB even if high memory available
  131.             ; (note: can't set both UMB_ONLY and LOW_ONLY)
  132. USE_TOPMEM equ 8    ; use the top of low memory if no high memory
  133.             ; (this is not always the best place to load)
  134. PATCH_RESIDENT equ 80h  ; patch resident code with actual memory block address
  135.  
  136. ;-----------------------------------------------------------------------
  137. ;
  138. ; DISPLAY_STRING    output a '$'-terminated string to standard output
  139. ; arguments:    string    the label of the string to be displayed
  140. ;        dataseg [opt] the segment of the string
  141. ;
  142. DISPLAY_STRING MACRO string,dataseg
  143. IFNB <dataseg>
  144.     push    ds
  145.     mov    ax,dataseg
  146.     mov    ds,ax
  147. ENDIF
  148.     mov    dx,offset string
  149.     mov    ah,9
  150.     int    21h
  151. IFNB <dataseg>
  152.     pop    ds
  153. ENDIF
  154.     ENDM
  155.  
  156. ;-----------------------------------------------------------------------
  157. ;
  158. ; CHECK_DOS_VER        ensure that the program is running under the proper
  159. ;            version of DOS, and terminate with an error message
  160. ;            specifying the minimum required version if not.
  161. ;
  162. CHECK_DOS_VER MACRO major,minor
  163.     LOCAL    bad_version_msg,version_OK
  164. IF major GE 5
  165.     mov    ax,3306h        ; get true DOS version
  166. ELSE
  167.     mov    ax,3000h
  168. ENDIF
  169.     int    21h
  170.     xchg    al,ah
  171.     cmp    ax,256*major + minor
  172.     jae    version_OK
  173. IFNDEF __TINY__
  174.     push    cs
  175.     pop    ds
  176. ENDIF
  177.     DISPLAY_STRING bad_version_msg
  178.     int    20h            ; terminate program
  179.  
  180. bad_version_msg label byte
  181.     db    "This program requires DOS "
  182.     db    major+'0',".",(minor/10)+'0',(minor mod 10)+'0'
  183.     db    " or higher.",13,10,"$"
  184.  
  185. version_OK:
  186.     ENDM
  187.  
  188. ;-----------------------------------------------------------------------
  189. ;
  190. ; IF_INSTALLED    conditionally branch somewhere if TSR is already installed
  191. ; arguments:
  192. ;    rescode segment of TSR code within executable (to get signature and
  193. ;            hook list)
  194. ;    rtype    type of segment reference: REL = paras offset from CS
  195. ;                       ABS = absolute segment number
  196. ;    dest    label to branch to if already installed
  197. ; at exit:
  198. ;    CF set if installed
  199. ;        AH = multiplex number
  200. ;        CX = version number
  201. ;    CF clear if not installed
  202. ;
  203. IF_INSTALLED MACRO rescode,rtype,dest
  204.     LOCAL    not_installed
  205. IFIDNI <rtype>,<REL>
  206.     mov    ax,cs
  207.     add    ax,rescode
  208. ELSE
  209. IFIDNI <rtype>,<RELBYTE>
  210.     mov    bx,rescode
  211.     ; note: loc must always be paragraph-aligned; TSRcode@ ensures this
  212.     mov    cl,4
  213.     shr    bx,cl
  214.     mov    ax,cs
  215.     add    ax,bx
  216. ELSE
  217.     mov    ax,rescode
  218. ENDIF
  219. ENDIF
  220.     extrn check_if_installed:DIST
  221.     call    check_if_installed
  222.     jnc    not_installed
  223.     jmp    dest
  224. not_installed:
  225.     ENDM
  226.  
  227. ;-----------------------------------------------------------------------
  228. ;
  229. ; INSTALL_TSR
  230. ; arguments:
  231. ;    loc    location of resident code
  232. ;    ltype    type of above location: REL = para offset from CS
  233. ;                    ABS = absolute paragraph number
  234. ;    siz    size of resident code
  235. ;    stype    type of above size: BYTE or PARA
  236. ;    extra    [opt] number of additional paragraphs needed in resident part
  237. ;    fit    [opt] FIRST (default) or BEST fit allocation
  238. ;    high    [opt] HIGHONLY to only use UMBs, TOPMEM to allocate block at
  239. ;            high end of conventional memory if no UMBs available,
  240. ;            LOWONLY to ignore UMBs, and TOPLOW to allocate at high
  241. ;            end of conventional memory whether or not UMBs are
  242. ;            available
  243. ;    init    [opt] function to call after installing TSR but before exiting
  244. ;    if_inst [opt] label to branch to if already installed
  245. ;    on_err    [opt] label to branch to if unable to install
  246. ;    more_flags [opt] label of byte containing additional flags to OR into
  247. ;           flags setup by <fit> and <high>
  248. ;
  249. ; if 'init' is specified, the indicated function will be called with
  250. ;    AX = segment at which TSR was loaded
  251. ; if 'if_inst' is specified, the indicated function will be jumped at with
  252. ;    AH = multiplex number
  253. ;    CX = version number
  254. ;
  255. INSTALL_TSR MACRO loc,ltype,siz,stype,extra,fit,high,init,if_inst,on_err,more_flags
  256.     LOCAL not_installed,install_failed,iflags
  257.     mov    bx,loc
  258. IFIDNI <ltype>,<REL>
  259.     mov    ax,cs
  260.     add    bx,ax
  261. ELSE
  262. IFIDNI <ltype>,<RELBYTE>
  263.     ; note: loc must always be paragraph-aligned; TSRcode@ ensures this
  264.     mov    cl,4
  265.     shr    bx,cl
  266.     mov    ax,cs
  267.     add    bx,ax
  268. ENDIF
  269. ENDIF    
  270.     push    bx
  271.     mov    ax,bx
  272.     extrn    check_if_installed:DIST
  273.     call    check_if_installed
  274.     pop    bx
  275.     jnc    not_installed
  276. install_failure:
  277. IFNB <if_inst>
  278.     jmp    if_inst
  279. ELSE
  280.     jmp short install_failed
  281. ENDIF
  282. not_installed:
  283.     cmp    al,1
  284.     je    install_failure
  285.     push    ax            ; remember multiplex number
  286. IFIDNI <stype>,<PARA>
  287.     mov    cx,siz
  288. ELSE
  289.     mov    ax,siz
  290.     add    ax,15            ; convert bytes to paragraphs
  291.     mov    cl,4
  292.     shr    ax,cl
  293.     mov    cx,ax
  294. ENDIF
  295. IFNB <extra>
  296.     mov    dx,extra
  297. ELSE
  298.     xor    dx,dx            ; no extra memory required
  299. ENDIF
  300.     pop    ax            ; get back multiplex number
  301.     iflags = 0
  302. IFDIFI <fit>,<FIRST>
  303.     iflags = iflags OR BEST_FIT
  304. ENDIF
  305. IFIDNI <high>,<HIGHONLY>
  306.     iflags = iflags OR UMB_ONLY
  307. ENDIF
  308. IFIDNI <high>,<LOWONLY>
  309.     iflags = iflags OR LOW_ONLY
  310. ENDIF
  311. IFIDNI <high>,<TOPMEM>
  312.     iflags = iflags OR USE_TOPMEM
  313. ENDIF
  314. IFIDNI <high>,<TOPLOW>
  315.     iflags = iflags OR USE_TOPMEM OR LOW_ONLY
  316. ENDIF
  317. IFDEF ALTMPX$PSP
  318.     iflags = iflags OR PATCH_RESIDENT
  319. ENDIF
  320.     mov    al,iflags
  321. IFNB <more_flags>
  322.     or    al,more_flags
  323. ENDIF
  324.     extrn $install_TSR:DIST
  325.     call    $install_TSR
  326.     ; if success, returns CF clear, AX=segment at which TSR was installed
  327.     jc    install_failed
  328. IFNB <&init>
  329.     call    init
  330. ENDIF
  331.     extrn $go_TSR:DIST
  332.     call    $go_TSR            ; never returns
  333.  
  334. install_failed:
  335. IFNB <on_err>
  336.     jmp    on_err
  337. ELSE
  338.     push    cs
  339.     pop    ds
  340.     DISPLAY_STRING cs:install_error_msg
  341.     mov    ax,4CFFh        ; exit with ERRORLEVEL 255
  342.     int    21h
  343.  
  344. install_error_msg db "Unable to go resident.",13,10,"$"
  345. ENDIF
  346.     ENDM
  347.  
  348.  
  349. ;-----------------------------------------------------------------------
  350. ;
  351. ; UNINSTALL    remove the TSR from memory
  352. ; arguments:
  353. ;    rescode segment of TSR code within executable (to get signature and
  354. ;            hook list)
  355. ;    rtype    type of segment reference: REL = paras offset from CS
  356. ;                       ABS = absolute segment number
  357. ;    on_err    [opt] label to branch to if unable to remove from memory
  358. ;
  359. ; If 'on_err' is omitted, check CF after this macro to determine whether
  360. ; the removal was successful (CF clear if successful, set on error)
  361. ;
  362. UNINSTALL MACRO rescode,rtype,on_err
  363.     LOCAL    success
  364. IFIDNI <rtype>,<REL>
  365.     mov    ax,cs
  366.     add    ax,rescode
  367. ELSE
  368. IFIDNI <rtype>,<RELBYTE>
  369.     mov    bx,rescode
  370.     ; note: loc must always be paragraph-aligned; TSRcode@ ensures this
  371.     mov    cl,4
  372.     shr    bx,cl
  373.     mov    ax,cs
  374.     add    ax,bx
  375. ELSE
  376.     mov    ax,rescode
  377. ENDIF
  378. ENDIF
  379.     extrn $uninstall_TSR:DIST
  380.     call    $uninstall_TSR
  381. IFNB <on_err>
  382.     jnc    success
  383.     jmp    on_err
  384. ENDIF
  385. success:
  386.     ENDM
  387.  
  388. ;-----------------------------------------------------------------------
  389. ;
  390. ;             I M P O R T A N T ! ! !
  391. ; Note: in order to work properly with the code in ALTMPX.ASM, all of
  392. ; the following macros must be used inside TSRcode@
  393. ;
  394.  
  395. ;-----------------------------------------------------------------------
  396. ;
  397. ; ISP_HEADER    set up Interrupt Sharing Protocol header for an interrupt
  398. ; arguments:
  399. ;    intr    interrupt number
  400. ;    reset    [opt] name of routine to perform hardware reset
  401. ;    eoi    [opt] if nonzero, this is the primary handler for a hardware int
  402. ; exported labels: (for example "ISP_HEADER 00h,reset_func,0")
  403. ;    INT00h_handler (public), ORIG_INT00h (public), HWRESET_00h,
  404. ;    EOI_FLAG_00h
  405. ;    [in addition, hw_reset_00h would be present for ISP_HEADER 00h,,0]
  406. ;
  407. ISP_HEADER MACRO intr,reset,eoi
  408. public INT&intr&_handler,ORIG_INT&intr
  409.     ASSUME    DS:NOTHING,ES:NOTHING,SS:NOTHING
  410. IFB <reset>
  411. hw_reset_&intr:
  412.     db    0CBh            ; RETF
  413. ENDIF ;reset
  414.  
  415. INT&intr&_handler:
  416.     db    0EBh,10h        ; short JMP to skip the header
  417. ORIG_INT&intr dd ?            ; previous handler in chain
  418.     dw   424Bh            ; ISP signature
  419. EOI_FLAG_&intr label byte
  420. IFB <eoi>
  421.     db   0                ; software int or secondary hardware int
  422. ELSE
  423. IF eoi eq 0
  424.     db   0                ; software int or secondary hardware int
  425. ELSE
  426.     db   80h            ; primary hardware int handler
  427. ENDIF ;eoi eq 0
  428. ENDIF ;B eoi
  429. IFB <reset>
  430. HWRESET_&intr: jmp short hw_reset_&intr
  431. ELSE
  432. HWRESET_&intr: jmp short reset
  433. ENDIF ;B reset
  434.     db   7 dup (0)
  435.     ENDM
  436.  
  437. ;-----------------------------------------------------------------------
  438. ;
  439. ; HOOKED_INTS        declare the interrupts this TSR hooks
  440. ; arguments:        up to 32 interrupt numbers
  441. ; exported labels:    HOOKED_INT_LIST (public)
  442. ;
  443. HOOKED_INTS MACRO a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,aa,ab,ac,ad,ae,af,over
  444. public HOOKED_INT_LIST
  445. HOOKED_INT_LIST label byte
  446. IFNB <over>
  447.     %out Too many interrupts hooked!
  448.     .err
  449. ENDIF ;NB over
  450.     IRP    intrpt,<a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,aa,ab,ac,ad,ae,af>
  451.         IFNB <intrpt>
  452.         IF intrpt ne 2Dh   ; ignore INT 2Dh if in the list
  453.             DB 0&&intrpt
  454.             DW INT&&intrpt&&_handler
  455.         ENDIF ;DIFI
  456.         ENDIF ;NB
  457.     ENDM
  458.     ;
  459.     ; the list terminator is INT 2Dh, since we know that one will always
  460.     ; be hooked; thus, all interrupts from 00h to FFh may be hooked
  461.     ;
  462.             DB 2Dh
  463.             DW INT2Dh_handler
  464.     ENDM
  465.  
  466. ;-----------------------------------------------------------------------
  467. ;
  468. ; ALTMPX    define the alternate multiplex interrupt handler for the program
  469. ; arguments:
  470. ;    manuf       one- to eight-character manufacturer's name
  471. ;    prodname   one- to eight-character product name
  472. ;    version       four-digit hex version number (hi byte = major, lo = minor)
  473. ;    descrip       [opt] string (max 63 char) describing the product
  474. ;    priv_funcs [opt] name of routine to handle private INT 2Dh functions
  475. ;    api_entry  [opt] name of FAR routine giving non-INT 2Dh API entry point
  476. ;    popup       [opt] name of function to call to request a popup
  477. ;    remover       [opt] name of function to call to remove TSR from memory
  478. ;    psp       [opt] if nonblank, set up patch word for memblk segment to
  479. ;             be returned if <remover> omitted; returns CS if both
  480. ;             <remover> and <psp> blank
  481. ; limitations on routines:
  482. ;    all: must be located inside TSRcode@
  483. ;    <priv_funcs>
  484. ;        input:    AL = function number (10h-FFh)
  485. ;            AH = multiplex number (ignore)
  486. ;            others available for handler
  487. ;        return: via IRET, with regs as appropriate for requested func
  488. ;    <api_entry>
  489. ;        input:    registers as desired (no limitations)
  490. ;        return: registers as desired (no limitations)
  491. ;    <popup>
  492. ;        input:    nothing
  493. ;        return: AL = status
  494. ;                01h can not pop up now, try again later
  495. ;                02h can not pop up yet, will do so when able
  496. ;                03h already popped up
  497. ;                04h unable to popup, user intervention required
  498. ;                    BX = standard reason code
  499. ;                    0000h unknown failure
  500. ;                    0001h int chain passes through memory
  501. ;                        which must be swapped out
  502. ;                    0002h swap-in failed
  503. ;                    CX = application's reason code if nonzero
  504. ;                FFh TSR popped up and was exited by user
  505. ;                    BX = return value
  506. ;                    0000h no return value
  507. ;                    0001h TSR unloaded
  508. ;                    0002h-00FFh reserved
  509. ;                    0100h-FFFFh application-specific
  510. ;    <remover>
  511. ;        input:    DX:BX = return address if uninstall successful
  512. ;        return: AL = status
  513. ;                01h unable to remove from memory
  514. ;                02h can't remove now, will do so when able
  515. ;                03h safe to remove, but no resident uninstaller
  516. ;                    (TSR still enabled)
  517. ;                    BX = segment of memory block
  518. ;                04h safe to remove, but no resident uninstaller
  519. ;                    (TSR now disabled)
  520. ;                    BX = segment of memory block
  521. ;                05h not safe to remove now, try again later
  522. ;                FFh successful (DX:BX were ignored)
  523. ;        return at DX:BX with AX destroyed if successful and <remover>
  524. ;            honors specific return address
  525. ;        if <remover> omitted, ALTMPX returns AL=03h
  526. ; exported labels:
  527. ;    INT2Dh_handler (public), ORIG_INT2Dh (public), HWRESET_2Dh,
  528. ;    EOI_FLAG_2Dh, hw_reset_00h, MULTIPLEX_NUMBER (public),
  529. ;    ALTMPX_SIGNATURE (public), ALTMPX$PSP [patch word]
  530. ;
  531. ALTMPX MACRO manuf,prodname,version,descrip,priv_funcs,api_entry,popup,remover,psp
  532.     LOCAL our_int_2Dh,int2D_func_00,int2D_func_01,int2D_func_02
  533.     LOCAL int2D_func_03,int2D_func_04
  534.     LOCAL func_is_supported,func_not_supported,func_supported_segDX
  535.     PUBLIC MULTIPLEX_NUMBER,ALTMPX_SIGNATURE,ALTMPX$PSP
  536.  
  537. ALTMPX_SIGNATURE label byte
  538.     db    manuf
  539. IF ($-ALTMPX_SIGNATURE) gt 8
  540.     ERR "Manufacturer name >8 chars"
  541. ELSEIF ($-ALTMPX_SIGNATURE) lt 8
  542.     db    (ALTMPX_SIGNATURE+8-$) dup (' ')
  543. ENDIF
  544.     db    prodname
  545. IF ($-ALTMPX_SIGNATURE) gt 16
  546.     ERR "Product name >8 chars"
  547. ELSEIF ($-ALTMPX_SIGNATURE) lt 16
  548.     db    (ALTMPX_SIGNATURE+16-$) dup (' ')
  549. ENDIF
  550. IFNB <descrip>
  551.     db    descrip
  552. ENDIF
  553.     db    0
  554. IF ($-ALTMPX_SIGNATURE) gt 80
  555.     ERR "Description >63 chars"
  556. ENDIF
  557.  
  558. ; save an additional byte by overlaying the null hardware reset handler over
  559. ; other code, if possible
  560. IFNB <remover>
  561. hw_reset_2Dh:                ; <remover> not blank
  562.     db    0CBh            ; RETF
  563. IFNDEF ALTMPX$PSP
  564. ALTMPX$PSP equ word ptr ($+12)        ; point harmlessly into the ISP header
  565. ENDIF
  566. ELSE
  567.    IFB <psp>
  568.       ALTMPX$PSP equ word ptr ($+12)    ; point harmlessly into the ISP header
  569.    ENDIF
  570. ENDIF
  571. IFNB <psp>
  572.    IFB <remover>
  573. hw_reset_2Dh:                ; <remover> blank but <psp> not
  574.     db    0CBh            ; RETF
  575.    ENDIF
  576. ENDIF
  577.                     ; if both <remover> and <psp> blank,
  578.                     ;   hw_reset_2Dh is defined below
  579.                     ; if <remover> is blank and <psp> not,
  580.                     ;   ALTMPX$PSP is defined below
  581.  
  582.     ISP_HEADER 2Dh,hw_reset_2Dh
  583.     cmp    ah,0            ; will be patched with multiplex number
  584. MULTIPLEX_NUMBER equ byte ptr ($-1)
  585.     je    our_int_2Dh
  586.     jmp    ORIG_INT2Dh
  587. our_int_2Dh:
  588.     sti                ; OK to interrupt from now on
  589.     cmp    al,0
  590.     je    int2D_func_00
  591.     cmp    al,2
  592. IFNB <api_entry>
  593.     jb    int2D_func_01
  594. ELSE
  595.   IFNB <popup>
  596.     jb    func_not_supported
  597.   ENDIF
  598. ENDIF
  599.     je    int2D_func_02
  600.     cmp    al,4
  601. IFNB <popup>
  602.     jb    int2D_func_03
  603. ENDIF ;popup
  604.     je    int2D_func_04
  605. IFNB <priv_funcs>
  606.     cmp    al,10h
  607.     jb    func_not_supported
  608.         jmp     priv_funcs
  609. ENDIF ;priv_funcs
  610. func_not_supported:
  611.     mov    al,0
  612.     iret
  613.  
  614. int2D_func_00:
  615.     mov    cx,version
  616.     mov    di,offset ALTMPX_SIGNATURE
  617. func_supported_segDX:
  618.     mov    dx,cs
  619. func_is_supported:
  620.     mov    al,0FFh
  621.     iret
  622.  
  623. IFNB <api_entry>
  624. int2D_func_01:
  625.     mov    bx,offset api_entry
  626.     jmp    func_supported_segDX
  627. ENDIF ;api_entry
  628.  
  629. int2D_func_02:
  630. IFNB <remover>
  631.     call    remover
  632. ELSE
  633. ;    mov    al,3            ; safe to remove, no resident uninstaller
  634.     inc    ax            ; AL was 02h, now 03h
  635. IFNB <psp>
  636.     mov    bx,0            ; will be patched at installation time
  637. ALTMPX$PSP equ word ptr ($-2)
  638. ELSE
  639.     mov    bx,cs
  640. hw_reset_2Dh equ near ptr ($-1) ; prev instruction happens to expand to 8Ch CBh
  641. ENDIF ;psp
  642. ENDIF ;remover
  643.     iret
  644.  
  645. IFNB <popup>
  646. int2D_func_03:
  647.     call    popup
  648.     iret
  649. ENDIF ;popup
  650.  
  651. int2D_func_04:
  652.     ;mov    al,4 ;not needed since AL=04h anyway
  653.     mov    dx,cs
  654.     mov    bx,offset cs:hooked_int_list
  655.     iret
  656.  
  657.     ENDM
  658.  
  659. ;-----------------------------------------------------------------------
  660. ;
  661. GRAB_INTERRUPT MACRO intnum,handler
  662.     TSRbss@
  663.     TSR_old_INT&intnum dd ?
  664.     TSRbssEnd@
  665.  
  666.     mov    ax,3500h+intnum
  667.     int    21h
  668.     mov    word ptr TSR_old_INT&intnum,bx
  669.     mov    word ptr TSR_old_INT&intnum+2,es
  670.     mov    dx,offset TGROUP:handler
  671.     mov    ax,2500h+intnum
  672.     int    21h
  673.     ENDM
  674.  
  675. ;-----------------------------------------------------------------------
  676. ;
  677. RESTORE_INTERRUPT MACRO intnum
  678.     push    ds
  679.     lds    dx,TSR_old_INT&intnum
  680.     mov    ax,2500h+intnum
  681.     int    21h
  682.     pop    ds
  683.     ENDM
  684.  
  685. ;-----------------------------------------------------------------------
  686.  
  687. .LIST
  688.